﻿using KinonekoSoftware.CodariaDB.Documents.Relationships;
using KinonekoSoftware.CodariaDB.Documents.Relationships.Characters;
using KinonekoSoftware.Studio.Models.DataParts.Relationships;
using KinonekoSoftware.Studio.Models.Graphs;


namespace KinonekoSoftware.Studio.Pages.Others.Relationships
{
    public class CharacterRelationshipGalleryViewModel : TabViewModelCore
    {
        private readonly RelationEngine  _engine_rel;
        private readonly InstanceCacheEngine _engine_cache;
        private readonly HashSet<string>     _IdPool;


        private InstanceCache _selected;

        private int  _version;
        private bool _isInspectPanelOpen;
        private bool _isEditMode;

        public CharacterRelationshipGalleryViewModel()
        {
            Platform.GetEngine<RelationEngine, InstanceCacheEngine>(
                                                                        out _,
                                                                        out _engine_rel, 
                                                                        out _engine_cache);

            _IdPool     = new HashSet<string>();
            _isEditMode = true;

            Graph         = new CharacterRelationshipGraph();
            Relationships = new ObservableCollection<CharacterRelationshipPresenter>();


            SwitchEditModeCommand     = new ActionCommand(DoSwitchEditModeCommand);
            RefreshRelationshipCommand = new ActionCommand(DoRefreshRelationshipCommand);
            
            AddRelationshipCommand    = new FuncCommand<InstanceCache>(DoAddRelationshipCommand);
            EditRelationshipCommand   = new FuncCommand<CharacterRelationshipPresenter>(DoEditRelationshipCommand);
            SwitchAppellationCommand  = new FuncCommand<CharacterRelationshipPresenter>(DoSwitchAppellationCommand);
            RemoveRelationshipCommand = new FuncCommand<CharacterRelationshipPresenter>(DoRemoveRelationshipCommand);

            _version    = _engine_cache.Version;
            Removable   = true;
            IsSingleton = true;
        }

        private void Initialized()
        {
            var relationships = _engine_rel.GetCharacterRelationships();

            Graph.Clear();
            Graph.AddVertexRange(_engine_cache.Get(InstanceType.Character));

            foreach (var relationship in relationships)
            {
                var presenter = new CharacterRelationshipPresenter
                {
                    Core = relationship,
                };
                
                //
                //
                presenter.GetInstance(_engine_cache);
                
                //
                //
                Graph.AddEdge(presenter);
                
                //
                //
                _IdPool.Add(relationship.SourceID);
                _IdPool.Add(relationship.TargetID);
            }
            
            _version = _engine_cache.Version;
        }

        protected override void OnStart()
        {
            Initialized();
            base.OnStart();
        }

        protected override void OnResume()
        {
            if (_version != _engine_cache.Version)
            {
                Initialized();
            }

            base.OnResume();
        }

        private static void DoSwitchAppellationCommand(CharacterRelationshipPresenter target)
        {

            if (target is null)
            {
                return;
            }

            target.SwitchAppellation();
        }

        private void DoSwitchEditModeCommand()
        {
            IsEditMode = !IsEditMode;
        }
        
        private void DoRefreshRelationshipCommand()
        {
            Initialized();
        }

        private async void DoAddRelationshipCommand(InstanceCache target)
        {
        }

        private async void DoEditRelationshipCommand(CharacterRelationshipPresenter target)
        {
          

        }


        private async void DoRemoveRelationshipCommand(CharacterRelationshipPresenter target)
        {
            if (target is null)
            {
                return;
            }

            //
            //
            if (!await RemoveItem())
            {
                return;
            }


            Graph.RemoveEdge(target);

            //
            //
            _engine_rel.RemoveRelation(target.Core);

            //
            //
            _IdPool.Remove(target.Core.TargetID);

            //
            //
            Relationships.Remove(target);
        }

        public CharacterRelationshipGraph                  Graph         { get; }
        public ObservableCollection<CharacterRelationshipPresenter> Relationships { get; }

        public ICommandEX SwitchEditModeCommand      { get; }
        public ICommandEX RefreshRelationshipCommand { get; }
        
        public ICommandEX AddRelationshipCommand     { get; }
        public ICommandEX EditRelationshipCommand    { get; }
        public ICommandEX SwitchAppellationCommand   { get; }
        public ICommandEX RemoveRelationshipCommand  { get; }


        public bool IsInspectPanelOpen
        {
            get => _isInspectPanelOpen;
            set => SetValue(ref _isInspectPanelOpen, value);
        }

        public bool IsEditMode
        {
            get => _isEditMode;
            set
            {
                SetValue(ref _isEditMode, value);
                Relationships.ForEach(x => x.IsEditMode = value);
            }
        }

        public InstanceCache Selected
        {
            get => _selected;
            set
            {
                SetValue(ref _selected, value);
                Graph.TryGetInEdges(value, out var edgeA);
                Graph.TryGetOutEdges(value, out var edgeB);

                var total = edgeA.Concat(edgeB);
                var id    = _selected.Id;
                Relationships.Clear();

                foreach (var relationship in total)
                {
                    relationship.SwitchInstance(id);
                    Relationships.Add(relationship);
                }

                IsInspectPanelOpen = value is not null;
            }
        }
    }
}